package lzlz000.generate;

import java.io.*;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.util.LinkedHashSet;
import java.util.Set;

/**
 * 生成POJO代码
 * addCol方法中有各种sql数据类型和java数据类型的对应，根据需要可自行修改
 * 生成的代码不包含 package名 使用IDEA，直接复制文件 在IDEA中粘贴到指定的package中会自动添加包名
 * 如果生成目录在当前项目下，请不要把直接生成的代码提交到代码仓库！
 * Create by lzlz at 2018/3/13 22:20
 * @author : lzlz
 */
public class EntityGenerate {
    private static String fields;
    private static Set<String> importSet;
    private static String className;
    private static String tableName;
    private static String path;
    private static PrimaryKeyGeneration generation;
    private static Connection conn = Connect.getConnection();

    public static void main(String args[])throws Exception{
        //----------------在这里配置-----------------
        //要获取所有的数据表的名字，就可以使用"%"来作为tableNamePattern 的参数，也可以用“tb_%”这样表示。
        String tableNamePattern ="%user";
        String removePrefix="^(sys_|tb_)";//需要去除的前缀
        path =System.getProperty("user.dir")+"\\生成\\entity";//生成java文件的目录
        generation = PrimaryKeyGeneration.IDENTITY;//主键非自增，通过UUID生成
        //------------------------------------------

        //conn.getCatalog()获得当前数据库名
        DatabaseMetaData dbmd = conn.getMetaData();
        ResultSet rs =  dbmd.getTables(conn.getCatalog(),"%",
                tableNamePattern,new String[]{"TABLE"});//"TABLE"意味着获取的内容是表 不包括视图存储过程等其他东西
        while(rs.next()) {
            String tableName = rs.getString("TABLE_NAME");
//            System.out.println(tableName);
            init(tableName,removePrefix);// 1 初始化内容
            //获取主键
            ResultSet  primaryKeyResultSet = dbmd.getPrimaryKeys(conn.getCatalog(),null, tableName);
            String keyName = null;
            while(primaryKeyResultSet.next()){
                keyName = primaryKeyResultSet.getString("COLUMN_NAME");
            }
            ResultSet colRet = dbmd.getColumns(conn.getCatalog(),"%", tableName,"%");
            while(colRet.next()) {
                String columnName = headToLowercase(colRet.getString("COLUMN_NAME"));
                String columnType = colRet.getString("TYPE_NAME");
                int datasize = colRet.getInt("COLUMN_SIZE");

                addCol(columnName,columnType,datasize,columnName.equals(keyName)); // 2 添加字段

//                int digits = colRet.getInt("DECIMAL_DIGITS");
//                int nullable = colRet.getInt("NULLABLE");
//                System.out.println(columnName+" "+columnType+" "+datasize+" "+digits+" "+ nullable);
            }
            writeToFile();// 3 写入文件
        }

    }
    //开头小写
    private static String headToLowercase (String str){
        return str.substring(0, 1).toLowerCase()+str.substring(1);
    }
    //把数据表名去除前缀转换为驼峰命名
    private static String Camel(String tableName, String removePrefix){
        String[] words = tableName.replaceFirst(removePrefix,"").split("_");
        StringBuilder camel = new StringBuilder();
        for (String word : words) {
            camel.append(word.substring(0, 1).toUpperCase()).append(word.substring(1));
        }
        return camel.toString();
    }
    private static void init(String table, String removePrefix){

        tableName = table;
        className = Camel(table,removePrefix);
        importSet = new LinkedHashSet<>();
        importSet.add("import lombok.Data;\n");
        importSet.add("import javax.persistence.*;\n");
        fields ="";
    }
    private static void addCol(String colName, String type, int size,boolean isPrimaryKey) throws Exception {

        String javaType;
        type=type.toLowerCase();
        if(type.matches("(.*varchar|.*text.*)")){
            javaType ="String";
        }else if(type.equals("bigint")){
            javaType ="long";
        }else if(type.matches(".*int")){//sqlserver int（有符号）和java int的最大值均为2^31-1
            javaType ="int";
        }else if(type.equals("datetime")){
            javaType ="Date";
            importSet.add("import java.util.Date;\n");
        }else if(type.equals("bit")&&size==1){
            javaType ="boolean";
        }else if(type.equals("decimal")){
            importSet.add("import java.math.BigDecimal;\n");
            javaType ="BigDecimal";
        }else if(type.equals("real")||type.equals("float")){
            javaType ="double";
        }else{
            System.out.println("表 "+tableName+" 中 存在不支持类型 "+type);
            return;
        }
        if (isPrimaryKey) {
            String annoGeneratedValue;
            switch (generation) {
                case UUID:
                    annoGeneratedValue="@GeneratedValue(generator=\"UUID\")";
                    break;
                case IDENTITY:
                    annoGeneratedValue="@GeneratedValue(strategy = GenerationType.IDENTITY)";
                    break;
                default:
                    throw new Exception("没有选择主键自增方式");
            }
            fields +=
                    "    @Id\n" +
                    "    "+annoGeneratedValue+"\n" +
                    "    "+javaType+" "+colName+";\n";
        }else{
            fields +=
                    "\n    @Column(name = \""+colName+"\")\n" +
                    "    "+javaType+" "+colName+";\n";
        }
    }
    private static String finish(){
        String importStr = importSet.stream().reduce((str1,str2)->str1+str2).orElse("\n");
        return importStr +
                "\n" +
                "@Table(name = \""+tableName+"\")\n" +
                "@Data\n" +
                "public class "+className+" {\n" +
                fields+"\n}";
    }

    private static void writeToFile() throws IOException {
        String fileName = className+".java";
        File dir = new File(path);
        if (dir.mkdirs()) {
            System.out.println("生成目录："+path);
        }
        File file = new File(path,fileName);
        if(file.exists()&&file.delete()){
            System.out.println(fileName+"文件已存在 删除并重新生成");

        }
        if (file.createNewFile()) {
            OutputStream out = new FileOutputStream(file);
            OutputStreamWriter writer = new OutputStreamWriter(out);
            writer.write(finish());
            writer.flush();
            writer.close();
            System.out.println("生成文件："+file.getPath());
        }else{
            System.out.println(fileName+"文件创建失败");
        }
    }
}
